package com.polaris.live.ui.backpack.fragment

import android.animation.ObjectAnimator
import android.os.Bundle
import android.text.TextUtils
import android.view.ViewGroup
import android.view.animation.AccelerateDecelerateInterpolator
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.blankj.utilcode.util.StringUtils
import com.blankj.utilcode.util.TimeUtils
import com.lxj.xpopup.XPopup
import com.polaris.live.R
import com.polaris.live.adapter.backpack.BackPackBubbleAdapter
import com.polaris.live.adapter.backpack.BackPackToolAdapter
import com.polaris.live.common.cacha.CacheUtil
import com.polaris.live.common.cacha.UserManager
import com.polaris.live.common.constant.CommonConst
import com.polaris.live.common.ext.convertArabicDigitsToNormal
import com.polaris.live.common.mvvm.base2.BaseVbFragment
import com.polaris.live.common.network.parseState
import com.polaris.live.common.util.AppCodeUtils
import com.polaris.live.common.util.NavigationBarUtils
import com.polaris.live.common.util.ToastGravity
import com.polaris.live.common.util.ViewUtils
import com.polaris.live.databinding.FragmentBubbleBinding
import com.polaris.live.dialog.ToolCommonDialog
import com.polaris.live.dialog.ToolSureBarrageCardDialog
import com.polaris.live.dialog.ToolSureCardDialog
import com.polaris.live.dialog.ToolSureDialog
import com.polaris.live.dialog.ToolSureVipCardDialog
import com.polaris.live.dialog.VipUseSuccessfulDialog
import com.polaris.live.dialog_fragment.GiveFragmentDialog
import com.polaris.live.dialog_fragment.room_background.fragment.RoomBackgroundFragment
import com.polaris.live.interface_bag.BackPackToolCallback
import com.polaris.live.interface_bag.BackPackToolImpl
import com.polaris.live.resp.back_resp.UserBackpackConsumableResp
import com.polaris.live.resp.back_resp.toUserBasicVo
import com.polaris.live.translation.R.string
import com.polaris.live.utils.image.ImageUtils
import com.polaris.live.utils.route.RoutePath
import com.polaris.live.utils.route.Router
import com.polaris.live.viewmodel.backpack.BackPackToolViewModel
import com.polaris.live.widget.AnimUtils
import com.polaris.live.widget.refresh.EmptyView

/**
 * BackpackToolFragment 道具
 *
 * @author Created by 半仙 on 2024/1/31/031 17:43
 */
class BackpackToolFragment : BaseVbFragment<BackPackToolViewModel, FragmentBubbleBinding>(),
    BackPackToolImpl {

    private val mType: Long by lazy {
        arguments?.getLong("type") ?: 0L
    }

    private val mAdapter by lazy { BackPackToolAdapter() }

    private var mBackPackToolCallback: BackPackToolCallback? = null

    private var mIsShow = false

    private val emptyView by lazy { EmptyView(requireContext()) }

    private var mFirstVisiblePosition = 0
    private var mLastVisiblePosition = 0
    override fun initView(savedInstanceState: Bundle?) {
        ViewUtils.setMargin(
            mBinding.viewBottomPleaseHolder,
            bottomMargin = NavigationBarUtils.getNavigationBarHeight(requireContext())
        )
        mBinding.root.post {
            emptyView.setEmptyTip(R.drawable.family_empty, StringUtils.getString(string.no_hava_data))
            emptyView.layoutParams = ViewGroup.LayoutParams(mBinding.root.width, mBinding.root.height)
            mAdapter.setEmptyView(emptyView)
        }

        val numberOfColumns = 3
        mBinding.recyclerView.layoutManager = GridLayoutManager(requireContext(), numberOfColumns)
        mBinding.recyclerView.adapter = mAdapter
        mBinding.recyclerView.itemAnimator = null
        mBinding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
                mBinding.recyclerView.post {
                    checkVisibleItems()
                }
            }
        })
        mBinding.swipe.setOnRefreshListener {
            mViewModel.getConsumableList()
        }
        mBinding.swipe.setEnableLoadMore(false)
        initListener()
        initObserver()
    }

    private fun checkVisibleItems() {
        val layoutManager = mBinding.recyclerView.layoutManager as LinearLayoutManager
        val firstVisiblePosition = layoutManager.findFirstVisibleItemPosition()
        val lastVisiblePosition = layoutManager.findLastVisibleItemPosition()
        if (mFirstVisiblePosition != firstVisiblePosition || lastVisiblePosition != mLastVisiblePosition) {
            if (firstVisiblePosition > mFirstVisiblePosition) {
                for (i in mFirstVisiblePosition until firstVisiblePosition) {
                    mAdapter.notifyItemChanged(i, "hide")
                }
            }
            if (firstVisiblePosition < mFirstVisiblePosition) {
                for (i in firstVisiblePosition until mFirstVisiblePosition) {
                    mAdapter.notifyItemChanged(i, "show")
                }
            }
            if (lastVisiblePosition > mLastVisiblePosition) {
                for (i in mLastVisiblePosition + 1..lastVisiblePosition) {
                    mAdapter.notifyItemChanged(i, "show")
                }
            }
            if (lastVisiblePosition < mLastVisiblePosition) {
                for (i in lastVisiblePosition + 1..mLastVisiblePosition) {
                    mAdapter.notifyItemChanged(i, "hide")
                }
            }
            mFirstVisiblePosition = firstVisiblePosition
            mLastVisiblePosition = lastVisiblePosition

        }
    }

    /**
     * 定时刷新
     */
    fun timerUpdate() {
        if (!isCreated()) {
            return
        }
        // 收集需要删除的索引
        val indicesToRemove = mutableListOf<Int>()
        val nowServerTime = CacheUtil.getServerTime()
        mAdapter.data.forEachIndexed { index, item ->
            when {
                item.expiredTime == null -> {} // 永久物品
                item.amount > 1 -> { //聚合物品
                    val remainingTime = item.expiredTime.toLong().minus(nowServerTime)
                    if (remainingTime < 0) {
                        item.backpackIds.remove(item.backpackId)
                        item.expiredTimes.removeAt(0)
                        val newBackpackId = item.backpackIds.firstOrNull()
                        if (newBackpackId != null) {
                            val data = item.copy(
                                amount = item.backpackIds.size.toLong(),
                                backpackId = newBackpackId,
                                expiredTime = item.expiredTimes.firstOrNull()
                            )
                            mAdapter.data[index] = data
                            mAdapter.notifyItemChanged(index)
                        } else {
                            indicesToRemove.add(index)
                        }
                    } else {
                        mAdapter.notifyItemChanged(index, "notify")
                    }
                }

                item.expiredTime.toLong() - nowServerTime > 0 -> {
                    mAdapter.notifyItemChanged(index, "notify")
                } // 未超时 刷新时间
                else -> {
                    indicesToRemove.add(index)
                }
            }
        }
        indicesToRemove.sortedDescending().forEach { index ->
            mAdapter.removeAt(index)
        }
    }

    /**
     * 更新数据
     */
    fun updateData() {
        if (!isCreated()) {
            return
        }
        mViewModel.getConsumableList()
    }

    private fun initObserver() {
        mViewModel.mConsumableLiveData.observe(this) { resultState ->
            mBinding.swipe.finishRefresh()
            parseState(resultState, { resultData ->
                mAdapter.setList(resultData)
            })
        }
        mViewModel.mUseConsumableLiveData.observe(this) { resultState ->
            parseState(resultState, { resultData ->
                if (resultData.vipLevel == null) {
                    ToastGravity.showGravity(resultData.showText)
                }
                mViewModel.getConsumableList()
            }, {
                ToastGravity.showGravity(it.errorMsg)
            })
        }
        mViewModel.mGiveConsumableLiveData.observe(this) { resultState ->
            parseState(resultState, { resp ->
                // 直接通过 find 查找匹配的 item 和 position
                val userBackpackConsumableResp = mAdapter.data.find { resp.backpackId in it.backpackIds }
                    ?: return@parseState

                // 找到对应的 backpackId 在 backpackIds 中的位置
                val positionOf = userBackpackConsumableResp.backpackIds.indexOf(resp.backpackId)
                    .takeIf { it != -1 } ?: return@parseState

                // 更新数据
                val amount = userBackpackConsumableResp.amount

                if (amount > 1) {
                    userBackpackConsumableResp.amount = amount - 1
                    userBackpackConsumableResp.backpackIds.removeAt(positionOf)
                    mAdapter.notifyItemChanged(mAdapter.data.indexOf(userBackpackConsumableResp))
                } else {
                    val indexOf = mAdapter.data.indexOf(userBackpackConsumableResp)
                    mAdapter.removeAt(indexOf)
                }
                ToastGravity.showGravity(StringUtils.getString(string.gift_successful))
            }, {
                ToastGravity.showGravity(it.errorMsg)
            })
        }
    }

    private fun initListener() {
        mAdapter.setOnItemChildClickListener { _, view, position ->
            val item = mAdapter.data[position]
            when (view.id) {
                R.id.tv_chick1 -> {
                    if (item.backpackId == BackPackBubbleAdapter.NOT_HAVE) return@setOnItemChildClickListener
                    showToolSureDialog(position, item)
                }
            }
        }

        mAdapter.setOnItemClickListener { _, _, position ->
            val item = mAdapter.data[position]
            if (mIsShow && mAdapter.getLastSelect() == position) {
                showDown()
                mAdapter.setSelect(-1)
                mBackPackToolCallback?.onBackPackSelectCallback(null)
                return@setOnItemClickListener
            }
            mAdapter.setSelect(position)
            mBackPackToolCallback?.onBackPackSelectCallback(item)
            setDownData(item)
            if (!mIsShow) {
                showUp()
            }
        }
        showDown(0)
        mBinding.root.post {
            mBinding.nesScrollView.viewTreeObserver.addOnScrollChangedListener {
                if (mIsShow) {
                    showDown()
                }
            }
        }
    }

    private fun showToolSureDialog(position: Int, item: UserBackpackConsumableResp) {
        val dialog = when (item.consumableType) {
            CommonConst.PackToolType.DISCOUNT_CARDS, CommonConst.PackToolType.vouchers -> {//折扣卡  代金券
                ToolSureCardDialog(
                    requireContext(),
                    item
                ) {
                    mBackPackToolCallback?.goShopping(CommonConst.DressUp.AVATAR_FRAME)
                }
            }

            CommonConst.PackToolType.VIP_CARD -> { //vip卡
                ToolSureVipCardDialog(
                    requireContext(),
                    item, {
                        GiveFragmentDialog.show(requireContext()) {
                            this.dismiss()
                            useConsumable(position, it.userId, item)
                        }
                    }, {
                        useConsumable(position, null, item)
                    })
            }

            CommonConst.PackToolType.DANMAKU_CARD -> { //广播卡 弹幕
                ToolSureBarrageCardDialog(
                    requireContext(),
                    item
                )
            }

            CommonConst.PackToolType.BACKGROUND_CARD -> { //自定义背景卡
                ToolCommonDialog(
                    requireContext(),
                    StringUtils.getString(string.tool_need_diy_background_use),
                    ImageUtils.imgPath(item.displayUrl),
                    mOnCanal = {
                        if (item.giveOnOther) {
                            GiveFragmentDialog.show(requireContext()) {
                                dismiss()
                                mViewModel.giveTool(item.consumableType.toInt(), it.userId)
                            }
                        } else {
                            ToastGravity.showGravity(StringUtils.getString(string.you_not_send_other_tool_card))
                        }

                    }, mOnSure = {
                        mBackPackToolCallback?.goBackpack(
                            CommonConst.DressUp.PARTY_BACKGROUND,
                            RoomBackgroundFragment.DIY
                        )
                    }
                )
            }

            else -> {
                ToolSureDialog(
                    requireContext(),
                    UserManager.getUser().toUserBasicVo(),
                    item.description ?: ""
                ) {
                    useConsumable(position, null, item)
                }
            }
        }
        XPopup.Builder(context)
            .moveUpToKeyboard(false)
            .isDestroyOnDismiss(true)
            .asCustom(dialog)
            .show()
    }

    /**
     * 使用道具
     */
    private fun useConsumable(position: Int, otherUserId: Long?, item: UserBackpackConsumableResp) {
        mViewModel.useConsumable(item.backpackId, otherUserId) {
            if (it.vipLevel != null) {
                if (otherUserId == null) {
                    VipUseSuccessfulDialog.show(requireContext(), it.vipLevel, item.name) {
                        Router.instance.setPath(RoutePath.VIP_CENTER_ACTIVITY)
                            .withInt("page", 1)
                            .withInt("level", it.vipLevel.toInt())
                            .navigation(requireContext())
                    }
                } else {
                    ToastGravity.showGravity(StringUtils.getString(string.gift_successful))
                }

            }
            if (item.amount > 1) {
                item.backpackIds.remove(item.backpackId)
                item.expiredTimes.removeAt(0)
                val newBackpackId = item.backpackIds.firstOrNull()
                val newExpiredTime = item.expiredTimes.firstOrNull()
                val newAmount = item.backpackIds.size.toLong()
                if (newBackpackId != null) {
                    val newData = item.copy(
                        amount = newAmount,
                        backpackId = newBackpackId,
                        expiredTime = newExpiredTime
                    )
                    mAdapter.data[position] = newData
                    mAdapter.notifyItemChanged(position)
                } else {
                    mAdapter.removeAt(position)
                }
            } else {
                mAdapter.removeAt(position)
            }

        }

    }

    private fun showUp() {
        mIsShow = true
        mBinding.tvContext.post {
            // 创建属性动画
            val translateYAnimator: ObjectAnimator =
                ObjectAnimator.ofFloat(
                    mBinding.consBottom,
                    "translationY",
                    mBinding.consBottom.height.toFloat(),
                    0f
                )
            translateYAnimator.interpolator = AccelerateDecelerateInterpolator()
            translateYAnimator.duration = 300 // 设置动画时长，单位毫秒
            // 启动动画
            AnimUtils.run(mBinding.consBottom, translateYAnimator)
        }
    }

    private fun setDownData(mUserBack: UserBackpackConsumableResp) {
        if (!TextUtils.isEmpty(mUserBack.description)) {
            mBinding.tvContext.text = mUserBack.sourceDescription ?: mUserBack.description
        }
        if (mUserBack.backpackId == BackPackBubbleAdapter.NOT_HAVE) {
            mBinding.tvTime.text =
                StringUtils.getString(string.not_get_it)
        } else {
            mUserBack.createTime.let {
                val millis2String =
                    TimeUtils.millis2String(it.toLong(), "yyyy-MM-dd").convertArabicDigitsToNormal()
                val showTime = if (AppCodeUtils.isAR()) {
                    "$millis2String${StringUtils.getString(string.get_it)}"
                } else {
                    "$millis2String${StringUtils.getString(string.get_it)}"
                }
                mBinding.tvTime.text = showTime
            }
        }
    }

    private fun showDown(durationTime: Long? = null) {
        mIsShow = false
        mBinding.tvContext.post {
            // 创建属性动画
            val translateYAnimator: ObjectAnimator =
                ObjectAnimator.ofFloat(
                    mBinding.consBottom,
                    "translationY",
                    0f,
                    mBinding.consBottom.height.toFloat()
                )
            translateYAnimator.interpolator = AccelerateDecelerateInterpolator()
            translateYAnimator.duration = if (durationTime == null) 300 else durationTime // 设置动画时长，单位毫秒
            // 启动动画
            AnimUtils.run(mBinding.consBottom, translateYAnimator)
        }
    }

    override fun onBackPackDataCallback(backPackList: List<UserBackpackConsumableResp>) {
        mAdapter.setList(backPackList)
    }

    override fun onBackPackSelectCallback(position: Int) {
        if (mAdapter.getLastSelect() == position) return
        mAdapter.setSelect(position)
    }

    fun setBackPackToolCallback(l: BackPackToolCallback) {
        mBackPackToolCallback = l
    }

    override fun onResume() {
        super.onResume()
        mViewModel.putBackpackNew(3L, null)
        if (mAdapter.data.isEmpty()) {
            mBackPackToolCallback?.onBackPackSelectCallback(null)
        }
        mBinding.root.post {
            val index = mAdapter.getLastSelect()
            if (index == -1) {
                val orNull = mAdapter.data.getOrNull(0) ?: return@post
                mAdapter.setSelect(0)
                mBackPackToolCallback?.onBackPackSelectCallback(orNull)
                setDownData(orNull)
                if (!mIsShow) {
                    showUp()
                }
            } else {
                val orNull = mAdapter.data.getOrNull(index) ?: return@post
                mBackPackToolCallback?.onBackPackSelectCallback(orNull)
                setDownData(orNull)
                if (!mIsShow) {
                    showUp()
                }
            }
        }
    }

    fun getType(): Long {
        return mType
    }

    override fun onDestroy() {
        super.onDestroy()
        mBackPackToolCallback = null
    }
}